'use strict';

let model = require('../../model/mongo/district.js');
let debug = require('debug')('district');
let fout = require('../../common/function.js').formatOutput;

function MongoDao() {
    let self = this instanceof MongoDao ? this : new MongoDao();
    return self;
}
let theProto = MongoDao.prototype;
module.exports = MongoDao;

theProto.findOne = function* (query) {
    let errCode = 0;
    let errMsg = null;
    let data = null;

    try {
        let result = yield model.findOne(query);
        errMsg = result.errors;
        data = result._doc;
    } catch (e) {
        errMsg = e.toString();
    }

    if (errMsg) {
        errCode = 10202;
        errMsg = 'district: query error,' + errMsg;
        return fout(errCode, errMsg);
    }
    return fout(errCode, errMsg, data);
};

theProto.findById = function*(id) {
    let query = {_id: id};
    let result = yield  this.findOne(query);
    return result;
};

theProto.findByPid = function*(pId) {
    debug('dao findByPid, pId=' + pId);
    let errCode = 0;
    let errMsg = null;
    let data = null;

    try {
        let result = yield model.find({pId: pId});
        errMsg = result.errors;
        data = result;
    } catch (e) {
        errMsg = e.toString();
    }

    if (errMsg) {
        errCode = 10202;
        errMsg = 'district: query error,' + errMsg;
        return fout(errCode, errMsg);
    }
    return fout(errCode, errMsg, data);
};

theProto.saveOne = function*(json) {
    //debug('district save, input', json);
    let errCode = 0;
    let errMsg = null;
    let data = null;

    let pId = json.pId || null;
    let item = {
        adCode: json.adCode,
        areaCode: json.areaCode,
        cityCode: json.cityCode,
        name: json.name,
        pId: pId,
        subId: json.subId,
        level: json.level,
        loc: {
            type: 'Point',
            coordinates: json.center
        }
    };

    let entity = new model(item);
    let result;
    try {
        result = yield entity.save();
        errMsg = result.errors;
        data = result._doc;
    } catch (e) {
        errMsg = e.toString();
    }

    if (errMsg) {
        errCode = 10201;
        errMsg = 'district: save error,' + errMsg;
        return fout(errCode, errMsg);
    }

    let _id = data._id;
    if (pId) { // update pId
        let tmp = yield this.updateSubId(pId.toString(), _id.toString());
        if (tmp.errCode !== 0) {
            return tmp;
        }
        data.parent = tmp.result;
    }

    return fout(errCode, errMsg, data);
};

/**
 * 添加一个subId到{id:pId}对应的数据中
 * @param pId
 * @param subId
 * @returns {{errCode: *, errMsg: *, result: *}}
 */
theProto.updateSubId = function*(pId, subId) {
    debug('district updateSubId input', pId, subId);
    let errCode = 0;
    let errMsg = null;
    let result;
    try {
        result = yield model.findOneAndUpdate(
            {_id: pId},
            {$addToSet: {subId: subId}},
            {new: true}
        );
        errMsg = result.errors;
    } catch (e) {
        errMsg = e.toString();
    }

    if (errMsg) {
        errCode = 10201;
        errMsg = 'district: save error,' + errMsg;
        return fout(errCode, errMsg);
    }
    return fout(errCode, errMsg, result);
};

theProto.findAndModify = function *(query, update, option) {
    let errCode = 0;
    let errMsg = null;
    let result;
    try {
        result = yield model.findOneAndUpdate(query, update, option);
        errMsg = result.errors;
    } catch (e) {
        errMsg = e.toString();
    }

    if (errMsg) {
        errCode = 10201;
        errMsg = 'district: save error,' + errMsg;
        return fout(errCode, errMsg);
    }
    return fout(errCode, errMsg, result);
};

//theProto.update = function *() {
//    let ret = yield model.update(query, update);
//    return ret;
//};

theProto.saveMany = function*(json) {
    let list = [];
    let result = yield this.__saveMany(json, list);
    return result;
};

// 存储数组
theProto.__saveMany = function*(json, list) {
    debug('saveMany', json);
    if (!Array.isArray(json)) {
        json = [json];
    }

    for (let i = 0; i < json.length; i++) {
        let result = yield this.__saveTree(json[i], list);
        if (result.errCode !== 0) {
            return result;
        }
    }

    return fout(0, null, {list: list});
};

// 存储树状结构
theProto.__saveTree = function*(tree, list) {
    debug('saveTree', tree);
    if (!tree || !list) return fout(10203, 'district: argument error');

    // center:[1,2] or center:"1,2"
    let center = tree.center;
    if (typeof center === 'string') {
        center = tree.center.split(',').map(function (item) {
            return Number(item);
        });
    }

    let entiry = {
        adCode: tree.adCode,
        areaCode: tree.areaCode,
        cityCode: tree.cityCode,
        name: tree.name,
        center: center,
        pId: tree.pId || null,
        subId: []
    };

    let result = yield this.saveOne(entiry);
    if (result.errCode !== 0) {
        return result;
    }
    result = result.result;
    let parent = result.parent;
    delete result.parent;
    //list.push(result);
    replaceSameId(list, result);
    if (parent) {
        replaceSameId(list, parent);
    }

    if (tree.districts && tree.districts.length > 0) {
        tree.districts.forEach(function (item) {
            item.pId = result._id;
        });

        result = yield this.__saveMany(tree.districts, list);
        if (result.errCode !== 0) {
            return result;
        }
    }

    return fout(0, null, {success: true});
};


function replaceSameId(list, doc) {
    let _id = doc._id.toString();
    let pos = -1;
    for (let i = 0; i < list.length; i++) {
        let item = list[i];
        if (item._id.toString() === _id) {
            pos = i;
            break;
        }
    }

    if (pos < 0) list.push(doc);
    list.splice(pos, 1, doc);
}


